home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / term / extras / source / term-source.lha / termPhone.c < prev    next >
C/C++ Source or Header  |  1995-02-07  |  17KB  |  763 lines

  1. /*
  2. **    termPhone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* RemoveDialEntry(LONG Entry):
  13.      *
  14.      *    Remove a phone book entry from the dial list.
  15.      */
  16.  
  17. VOID __regargs
  18. RemoveDialEntry(LONG Entry)
  19. {
  20.     LONG Count = Phonebook[Entry] -> Count,i;
  21.  
  22.     for(i = 0 ; i < NumPhoneEntries ; i++)
  23.     {
  24.         if(Phonebook[i] -> Count > Count)
  25.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Header -> Name);
  26.     }
  27.  
  28.     Phonebook[Entry] -> Count = -1;
  29.  
  30.     SPrintf(Phonebook[Entry] -> Node -> LocalName,"      %s",Phonebook[Entry] -> Header -> Name);
  31. }
  32.  
  33.     /* RemoveDialNode(struct PhoneNode *Node):
  34.      *
  35.      *    Remove a node from the dialing list.
  36.      */
  37.  
  38. VOID __regargs
  39. RemoveDialNode(struct PhoneNode *Node)
  40. {
  41.     if(Node)
  42.     {
  43.             /* If it's got a name it was built in the phone book panel,
  44.              * else the ARexx interface has linked it into the list.
  45.              */
  46.  
  47.         if(Node -> VanillaNode . ln_Name && Node -> VanillaNode . ln_Name[0])
  48.         {
  49.             LONG Count = Node -> Entry -> Count,i;
  50.  
  51.                 /* Adjust all entries. */
  52.  
  53.             for(i = 0 ; i < NumPhoneEntries ; i++)
  54.             {
  55.                 if(Phonebook[i] -> Count > Count)
  56.                     Phonebook[i] -> Count--;
  57.             }
  58.  
  59.                 /* Can the index count. */
  60.  
  61.             Node -> Entry -> Count = -1;
  62.         }
  63.     }
  64. }
  65.  
  66.     /* SortToList(struct PhoneNode *PhoneNode):
  67.      *
  68.      *    Add a node to the dial list.
  69.      */
  70.  
  71. VOID __regargs
  72. SortToList(struct PhoneNode *PhoneNode)
  73. {
  74.         /* No dial list prepared? Let's create one! */
  75.  
  76.     if(!DialList)
  77.     {
  78.         if(DialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  79.             NewList(DialList);
  80.     }
  81.  
  82.         /* Do we have a dial list to mangle? */
  83.  
  84.     if(DialList)
  85.     {
  86.         struct PhoneNode *NewNode;
  87.  
  88.             /* Create a new node to be added to the dial list. */
  89.  
  90.         if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  91.         {
  92.             struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head;
  93.  
  94.                 /* Take care of the name and the corresponding phone book entry. */
  95.  
  96.             NewNode -> VanillaNode . ln_Name    = NewNode -> LocalName;
  97.             NewNode -> Entry            = PhoneNode -> Entry;
  98.  
  99.             strcpy(NewNode -> LocalName,PhoneNode -> LocalName);
  100.  
  101.                 /* Install back-link. */
  102.  
  103.             NewNode -> Entry -> Node = NewNode;
  104.  
  105.                 /* Sort the node into the list. */
  106.  
  107.             while(Node -> VanillaNode . ln_Succ)
  108.             {
  109.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  110.                 {
  111.                     if(Node == (struct PhoneNode *)DialList -> lh_Head)
  112.                         AddHead(DialList,&NewNode -> VanillaNode);
  113.                     else
  114.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  115.  
  116.                     return;
  117.                 }
  118.  
  119.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  120.             }
  121.  
  122.             AddTail(DialList,&NewNode -> VanillaNode);
  123.         }
  124.     }
  125. }
  126.  
  127.     /* FreeDialList(BYTE ClearAll):
  128.      *
  129.      *    Release the contents of the dial list.
  130.      */
  131.  
  132. VOID __regargs
  133. FreeDialList(BYTE ClearAll)
  134. {
  135.     if(DialList)
  136.     {
  137.         struct PhoneNode *SubNode,*NextNode;
  138.  
  139.         for(SubNode = (struct PhoneNode *)DialList -> lh_Head ; NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ ; SubNode = NextNode)
  140.         {
  141.             if(ClearAll || !SubNode -> VanillaNode . ln_Name || !SubNode -> VanillaNode . ln_Name[0])
  142.                 FreeVecPooled(SubNode);
  143.         }
  144.  
  145.         FreeVecPooled(DialList);
  146.  
  147.         DialList = NULL;
  148.     }
  149. }
  150.  
  151.     /* CreatePhoneList():
  152.      *
  153.      *    Turn the array of pointers to phonebook entries into
  154.      *    a linked standard Amiga List (gadtools needs this).
  155.      */
  156.  
  157. struct List *
  158. CreatePhoneList()
  159. {
  160.     struct List *PhoneList;
  161.  
  162.     if(Phonebook && NumPhoneEntries)
  163.     {
  164.         struct PhoneNode *PhoneNode;
  165.  
  166.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  167.         {
  168.             LONG i;
  169.  
  170.             NewList(PhoneList);
  171.  
  172.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  173.  
  174.             for(i = 0 ; i < NumPhoneEntries ; i++)
  175.             {
  176.                 if(Phonebook[i] -> Count != -1)
  177.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  178.                 else
  179.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Header -> Name);
  180.  
  181.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  182.  
  183.                 Phonebook[i] -> Node = &PhoneNode[i];
  184.  
  185.                 PhoneNode[i] . Entry = Phonebook[i];
  186.  
  187.                 AddTail(PhoneList,&PhoneNode[i]);
  188.             }
  189.  
  190.             return(PhoneList);
  191.         }
  192.     }
  193.     else
  194.     {
  195.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  196.         {
  197.             NewList(PhoneList);
  198.  
  199.             return(PhoneList);
  200.         }
  201.     }
  202.  
  203.     return(NULL);
  204. }
  205.  
  206.     /* DeletePhoneList(struct List *PhoneList):
  207.      *
  208.      *    Delete the entries listed in the Amiga List
  209.      *    created by the routine above.
  210.      */
  211.  
  212. VOID __regargs
  213. DeletePhoneList(struct List *PhoneList)
  214. {
  215.     if(PhoneList)
  216.         FreeVecPooled(PhoneList);
  217. }
  218.  
  219.     /* Compare(struct PhoneEntry **A,struct PhoneEntry **B):
  220.      *
  221.      *    Comparison subroutine required by the QuickSort
  222.      *    call below.
  223.      */
  224.  
  225. STATIC int __stdargs
  226. Compare(struct PhoneEntry **A,struct PhoneEntry **B)
  227. {
  228.         /* Has entry A been selected? */
  229.  
  230.     if((*A) -> Count == -1)
  231.     {
  232.             /* If entry B isn't selected either, compare the
  233.              * names lexically, else entry B is supposed
  234.              * to be `smaller' than entry A.
  235.              */
  236.  
  237.         if((*B) -> Count == -1)
  238.             return(Stricmp((*A) -> Header -> Name,(*B) -> Header -> Name));
  239.         else
  240.             return(1);
  241.     }
  242.     else
  243.     {
  244.             /* If entry B isn't selected, entry A is supposed
  245.              * to be `smaller' than entry B, else return
  246.              * the difference between both entries.
  247.              */
  248.  
  249.         if((*B) -> Count == -1)
  250.             return(-1);
  251.         else
  252.             return((*A) -> Count - (*B) -> Count);
  253.     }
  254. }
  255.  
  256.     /* SortPhoneEntries():
  257.      *
  258.      *    Sorts the current phone list array in ascending order.
  259.      */
  260.  
  261. VOID
  262. SortPhoneEntries()
  263. {
  264.     qsort((APTR)Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),Compare);
  265. }
  266.  
  267.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  268.      *
  269.      *    Free the memory allocated for a TimeDateNode and
  270.      *    the associated data table.
  271.      */
  272.  
  273. VOID __regargs
  274. FreeTimeDateNode(struct TimeDateNode *Node)
  275. {
  276.     FreeVecPooled(Node -> Table);
  277.  
  278.     FreeVecPooled(Node);
  279. }
  280.  
  281.     /* FreeTimeDateList(struct List *List):
  282.      *
  283.      *    Free a list of TimeDateNodes.
  284.      */
  285.  
  286. VOID __regargs
  287. FreeTimeDateList(struct List *List)
  288. {
  289.     if(List)
  290.     {
  291.         struct Node *Node = List -> lh_Head,*NextNode;
  292.  
  293.         while(NextNode = Node -> ln_Succ)
  294.         {
  295.             Remove(Node);
  296.  
  297.             FreeTimeDateNode((struct TimeDateNode *)Node);
  298.  
  299.             Node = NextNode;
  300.         }
  301.     }
  302. }
  303.  
  304.     /* CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst):
  305.      *
  306.      *    Copies the TimeDateNode list from one location into
  307.      *    another.
  308.      */
  309.  
  310. VOID __regargs
  311. CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst)
  312. {
  313.     struct TimeDateNode *FromNode,*ToNode;
  314.  
  315.     FromNode = (struct TimeDateNode *)From -> lh_Head;
  316.  
  317.     if(SkipFirst)
  318.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  319.  
  320.     while(FromNode -> VanillaNode . ln_Succ)
  321.     {
  322.         if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  323.         {
  324.             CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  325.  
  326.             ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  327.  
  328.             if(ToNode -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  329.             {
  330.                 CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  331.  
  332.                 AddTail(To,&ToNode -> VanillaNode);
  333.             }
  334.             else
  335.                 FreeVecPooled(ToNode);
  336.         }
  337.  
  338.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  339.     }
  340. }
  341.  
  342.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  343.      *
  344.      *    Adapt the title and comment of a TimeDateNode.
  345.      */
  346.  
  347. VOID __regargs
  348. AdaptTimeDateNode(struct TimeDateNode *Node)
  349. {
  350.     STRPTR Comment = Node -> Header . Comment[0] ? Node -> Header . Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  351.  
  352.     if(Node -> Header . Month == -1)
  353.     {
  354.         if(Node -> Header . Day == -1)
  355.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  356.         else
  357.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  358.     }
  359.     else
  360.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Header . Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Header . Month),Comment);
  361. }
  362.  
  363.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  364.      *
  365.      *    Comparison routine required by SortTimeTable().
  366.      */
  367.  
  368. STATIC int __stdargs
  369. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  370. {
  371.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  372. }
  373.  
  374.     /* SortTimeTable(struct TimeDateNode *Node):
  375.      *
  376.      *    Sort the time table associated with a
  377.      *    TimeDateNode in ascending order.
  378.      */
  379.  
  380. VOID __regargs
  381. SortTimeTable(struct TimeDateNode *Node)
  382. {
  383.     qsort((APTR)Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  384. }
  385.  
  386.     /* BuildTimeList(struct TimeDateNode *Node):
  387.      *
  388.      *    Build a read-to-display time table list from a TimeDateNode.
  389.      */
  390.  
  391. struct List * __regargs
  392. BuildTimeList(struct TimeDateNode *Node)
  393. {
  394.     struct List *List;
  395.  
  396.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  397.     {
  398.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  399.         UBYTE         LocalBuffer[40];
  400.         LONG         i;
  401.  
  402.         NewList(List);
  403.  
  404.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  405.         {
  406.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  407.             Time[i] . Time            = Node -> Table[i] . Time;
  408.  
  409.             FormatTime(LocalBuffer,Time[i] . Time / 6,(Time[i] . Time % 6) * 10,-1);
  410.  
  411.             LocalBuffer[19] = 0;
  412.  
  413.             strcpy(Time[i] . Name,LocalBuffer);
  414.  
  415.             AddTail(List,&Time[i]);
  416.         }
  417.     }
  418.  
  419.     return(List);
  420. }
  421.  
  422.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  423.      *
  424.      *    Resize the time table associated with a TimeDateNode.
  425.      */
  426.  
  427. BYTE __regargs
  428. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  429. {
  430.     if(Count != Node -> Table[0] . Count)
  431.     {
  432.         struct TimeDate *Table;
  433.  
  434.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  435.         {
  436.             LONG i;
  437.  
  438.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  439.  
  440.             if(Count > Node -> Table[0] . Count)
  441.             {
  442.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  443.                 {
  444.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  445.  
  446.                     Table[i] . Time = Time;
  447.                 }
  448.             }
  449.  
  450.             for(i = 0 ; i < Count ; i++)
  451.                 Table[i] . Count = Count;
  452.  
  453.             FreeVecPooled(Node -> Table);
  454.  
  455.             Node -> Table = Table;
  456.  
  457.             return(TRUE);
  458.         }
  459.         else
  460.             return(FALSE);
  461.     }
  462.     else
  463.         return(TRUE);
  464. }
  465.  
  466.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  467.      *
  468.      *    Delete a single timetable entry from a TimeDateNode.
  469.      */
  470.  
  471. BYTE __regargs
  472. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  473. {
  474.     struct TimeDate    *Table;
  475.     LONG         Count = Node -> Table[0] . Count - 1;
  476.  
  477.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  478.     {
  479.         LONG i,j;
  480.  
  481.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  482.         {
  483.             if(i != Index)
  484.             {
  485.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  486.  
  487.                 Table[j++] . Count = Count;
  488.             }
  489.         }
  490.  
  491.         FreeVecPooled(Node -> Table);
  492.  
  493.         Node -> Table = Table;
  494.  
  495.         return(TRUE);
  496.     }
  497.     else
  498.         return(FALSE);
  499. }
  500.  
  501.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  502.      *
  503.      *    Create a new TimeDateNode including time table entries.
  504.      */
  505.  
  506. struct TimeDateNode * __regargs
  507. CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count)
  508. {
  509.     struct TimeDateNode *Node;
  510.  
  511.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  512.     {
  513.         if(Node -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  514.         {
  515.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  516.  
  517.             Node -> Header . Month                = Month;
  518.             Node -> Header . Day                = Day;
  519. /*
  520.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  521.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    =  6 * 60;
  522.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  523.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    =  6 * 60;
  524. */
  525.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  526.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  527.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  528.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  529.             Node -> Table[0] . Time                = DT_GET_TIME( 8,0);
  530.             Node -> Table[0] . Count            = Count;
  531.  
  532.             if(Count > 1)
  533.             {
  534. /*
  535.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  536.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 12 * 60;
  537.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  538.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 12 * 60;
  539. */
  540.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  541.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  542.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  543.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  544.                 Node -> Table[1] . Time                = DT_GET_TIME(18,0);
  545.                 Node -> Table[1] . Count            = Count;
  546.             }
  547.  
  548.             strcpy(Node -> Header . Comment,Comment);
  549.  
  550.             AdaptTimeDateNode(Node);
  551.  
  552.             return(Node);
  553.         }
  554.         else
  555.             FreeVecPooled(Node);
  556.     }
  557.  
  558.     return(NULL);
  559. }
  560.  
  561.     /* RemPhoneEntry(LONG Num):
  562.      *
  563.      *    Remove a given entry from the phone book.
  564.      */
  565.  
  566. VOID __regargs
  567. RemPhoneEntry(LONG Num)
  568. {
  569.     struct PhoneEntry    *Entry;
  570.     LONG             i;
  571.  
  572.     Entry = Phonebook[Num];
  573.  
  574.     for(i = Num ; i < NumPhoneEntries ; i++)
  575.         Phonebook[i] = Phonebook[i + 1];
  576.  
  577.     Phonebook[NumPhoneEntries--] = NULL;
  578.  
  579.     if(Entry -> Config)
  580.         DeleteConfiguration(Entry -> Config);
  581.  
  582.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  583.  
  584.     FreeVecPooled(Entry);
  585. }
  586.  
  587.     /* NewPhoneEntry():
  588.      *
  589.      *    Create a new phone book entry with default values and
  590.      *    add it to the array. Expand the phone book if necessary.
  591.      */
  592.  
  593. BYTE
  594. NewPhoneEntry()
  595. {
  596.     struct PhoneEntry    **PrivatePhonebook;
  597.     LONG             PrivatePhoneSize,i;
  598.  
  599.         /* The phone book is filled `to the brim', so let's expand
  600.          * it.
  601.          */
  602.  
  603.     if(NumPhoneEntries + 1 > PhoneSize)
  604.     {
  605.             /* Allocate another phone book. */
  606.  
  607.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  608.         {
  609.                 /* Copy the data. */
  610.  
  611.             if(Phonebook && PhoneSize)
  612.             {
  613.                 for(i = 0 ; i < PhoneSize ; i++)
  614.                     PrivatePhonebook[i] = Phonebook[i];
  615.  
  616.                     /* Remove the old phonebook. */
  617.  
  618.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  619.             }
  620.  
  621.                 /* Assign the new pointers. */
  622.  
  623.             Phonebook = PrivatePhonebook;
  624.             PhoneSize = PrivatePhoneSize;
  625.         }
  626.         else
  627.             return(FALSE);
  628.     }
  629.  
  630.         /* Allocate another entry and add it to the phone book. */
  631.  
  632.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  633.     {
  634.         if(Phonebook[NumPhoneEntries] -> Config = CreateConfiguration(FALSE))
  635.         {
  636.             struct TimeDateNode *TimeDateNode;
  637.  
  638.             Phonebook[NumPhoneEntries] -> Header = (struct PhoneHeader *)(Phonebook[NumPhoneEntries] + 1);
  639.  
  640.             strcpy(Phonebook[NumPhoneEntries] -> Header -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  641.  
  642.             Phonebook[NumPhoneEntries] -> Count = -1;
  643.  
  644.             NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  645.  
  646.             if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  647.                 AddTail((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList,&TimeDateNode -> VanillaNode);
  648.  
  649.             NumPhoneEntries++;
  650.  
  651.             return(TRUE);
  652.         }
  653.  
  654.         FreeVecPooled(Phonebook[NumPhoneEntries]);
  655.  
  656.         Phonebook[NumPhoneEntries] = NULL;
  657.     }
  658.  
  659.     return(FALSE);
  660. }
  661.  
  662.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
  663.      *
  664.      *    Create a new phone entry array (so-called phone book).
  665.      */
  666.  
  667. struct PhoneEntry ** __regargs
  668. CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
  669. {
  670.     struct PhoneEntry **PhoneEntry = NULL;
  671.  
  672.     if(Size)
  673.     {
  674.             /* Round the number of phone entries to a
  675.              * multiple of eight.
  676.              */
  677.  
  678.         *AllocSize = (Size + 7) & ~7;
  679.  
  680.             /* Create the list of pointers. */
  681.  
  682.         if(PhoneEntry = (struct PhoneEntry **)AllocVecPooled(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY | MEMF_CLEAR))
  683.         {
  684.                 /* And create some entries if necessary. */
  685.  
  686.             if(CreateEntries)
  687.             {
  688.                 BYTE Success = TRUE;
  689.                 LONG i;
  690.  
  691.                 for(i = 0 ; Success && i < Size ; i++)
  692.                 {
  693.                     if(PhoneEntry[i] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  694.                     {
  695.                         if(PhoneEntry[i] -> Config = CreateConfiguration(FALSE))
  696.                         {
  697.                             PhoneEntry[i] -> Header = (struct PhoneHeader *)(PhoneEntry[i] + 1);
  698.  
  699.                             NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  700.                         }
  701.                         else
  702.                             Success = FALSE;
  703.                     }
  704.                     else
  705.                         Success = FALSE;
  706.                 }
  707.  
  708.                 if(!Success)
  709.                 {
  710.                     for(i = 0 ; i < *AllocSize ; i++)
  711.                     {
  712.                         if(PhoneEntry[i])
  713.                         {
  714.                             if(PhoneEntry[i] -> Config)
  715.                                 DeleteConfiguration(PhoneEntry[i] -> Config);
  716.  
  717.                             FreeVecPooled(PhoneEntry[i]);
  718.                         }
  719.                     }
  720.  
  721.                     FreeVecPooled(PhoneEntry);
  722.  
  723.                     return(NULL);
  724.                 }
  725.             }
  726.         }
  727.     }
  728.  
  729.     return(PhoneEntry);
  730. }
  731.  
  732.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
  733.      *
  734.      *    Deallocates a given phone book and its entries if necessary.
  735.      */
  736.  
  737. VOID __regargs
  738. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BYTE FreeEntries)
  739. {
  740.     if(Phonebook)
  741.     {
  742.         if(FreeEntries)
  743.         {
  744.             LONG i;
  745.  
  746.             for(i = 0 ; i < Size ; i++)
  747.             {
  748.                 if(Phonebook[i])
  749.                 {
  750.                     FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  751.  
  752.                     if(Phonebook[i] -> Config)
  753.                         DeleteConfiguration(Phonebook[i] -> Config);
  754.  
  755.                     FreeVecPooled(Phonebook[i]);
  756.                 }
  757.             }
  758.         }
  759.  
  760.         FreeVecPooled(Phonebook);
  761.     }
  762. }
  763.